Fix HVM event handling some more.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 13 Feb 2006 14:58:50 +0000 (15:58 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 13 Feb 2006 14:58:50 +0000 (15:58 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/io.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/arch/x86/hvm/vmx/io.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/io.h

index 9f32792e8fa4a4e61fa10468b726c95bcea45db1..39d53cccd5a51ffb758026d5e59fbf0a90ce4aac 100644 (file)
@@ -704,7 +704,6 @@ void hvm_wait_io(void)
     {
         /* Clear master flag, selector flag, event flag each in turn. */
         v->vcpu_info->evtchn_upcall_pending = 0;
-        smp_mb__before_clear_bit();
         clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
         smp_mb__after_clear_bit();
         if ( test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]) )
@@ -727,6 +726,31 @@ void hvm_wait_io(void)
         v->vcpu_info->evtchn_upcall_pending = 1;
 }
 
+void hvm_safe_block(void)
+{
+    struct vcpu *v = current;
+    struct domain *d = v->domain;    
+    int port = iopacket_port(d);
+
+    for ( ; ; )
+    {
+        /* Clear master flag & selector flag so we will wake from block. */
+        v->vcpu_info->evtchn_upcall_pending = 0;
+        clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
+        smp_mb__after_clear_bit();
+
+        /* Event pending already? */
+        if ( test_bit(port, &d->shared_info->evtchn_pending[0]) )
+            break;
+
+        do_sched_op(SCHEDOP_block, 0);
+    }
+
+    /* Reflect pending event in selector and master flags. */
+    set_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
+    v->vcpu_info->evtchn_upcall_pending = 1;
+}
+
 /*
  * Local variables:
  * mode: C
index b7bccf9b9980bdb075710f9473290cbe284bf170..1c83f4a79a09b3d875cd94e2515fb8b8972a4afc 100644 (file)
@@ -25,7 +25,6 @@
 #include <xen/sched.h>
 #include <xen/irq.h>
 #include <xen/softirq.h>
-#include <xen/hypercall.h>
 #include <asm/current.h>
 #include <asm/io.h>
 #include <asm/shadow.h>
@@ -1812,16 +1811,14 @@ static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
     inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL);
     __update_guest_eip(vmcb, inst_len);
 
-    if ( !v->vcpu_id ) {
+    if ( !v->vcpu_id )
         next_pit = get_pit_scheduled(v, vpit);
-    }
     next_wakeup = get_apictime_scheduled(v);
-    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
+    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
         next_wakeup = next_pit;
-    }
     if ( next_wakeup != - 1 )
         set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
-    do_sched_op(SCHEDOP_block, 0);
+    hvm_safe_block();
 }
 
 
@@ -2434,7 +2431,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
 #else
         svm_store_cpu_user_regs(&regs, v);
         domain_pause_for_debugger();  
-        do_sched_op(SCHEDOP_yield, 0);
 #endif
     }
     break;
index 6c56e58127e2bbb118d3fc78a71da20a4b6ca1a8..5d45a4c25e4e3800f3bcf755a1902c15c75e8abd 100644 (file)
@@ -487,16 +487,16 @@ int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa)
  */
 void svm_do_resume(struct vcpu *v) 
 {
-    struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+    struct domain *d = v->domain;
+    struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit;
     
-    if ( event_pending(v) ||
+    if ( test_bit(iopacket_port(d), &d->shared_info->evtchn_pending[0]) ||
          test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
         hvm_wait_io();
 
     /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( vpit->first_injected ) {
+    if ( vpit->first_injected )
         pickup_deactive_ticks(vpit);
-    }
     svm_set_tsc_shift(v, vpit);
     
     /* We can't resume the guest if we're waiting on I/O */
index b36ceb15f67500b8232ff6827f43b82d791e653b..b7a27f904a88e586271f5e9f00981334953d4ad2 100644 (file)
@@ -173,11 +173,12 @@ asmlinkage void vmx_intr_assist(void)
 
 void vmx_do_resume(struct vcpu *v)
 {
-    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    struct domain *d = v->domain;
+    struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
 
     vmx_stts();
 
-    if ( event_pending(v) ||
+    if ( test_bit(iopacket_port(d), &d->shared_info->evtchn_pending[0]) ||
          test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
         hvm_wait_io();
 
index fd0edf127264f5ba2d1065b003a0c063b4043648..05517ae291c69a00eb1936256efa97efd457a268 100644 (file)
@@ -25,7 +25,6 @@
 #include <xen/irq.h>
 #include <xen/softirq.h>
 #include <xen/domain_page.h>
-#include <xen/hypercall.h>
 #include <asm/current.h>
 #include <asm/io.h>
 #include <asm/shadow.h>
@@ -1643,16 +1642,14 @@ void vmx_vmexit_do_hlt(void)
     struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
     s_time_t   next_pit=-1,next_wakeup;
 
-    if ( !v->vcpu_id ) {
+    if ( !v->vcpu_id )
         next_pit = get_pit_scheduled(v,vpit);
-    }
     next_wakeup = get_apictime_scheduled(v);
-    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
+    if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
         next_wakeup = next_pit;
-    }
     if ( next_wakeup != - 1 ) 
         set_timer(&current->arch.hvm_vmx.hlt_timer, next_wakeup);
-    do_sched_op(SCHEDOP_block, 0);
+    hvm_safe_block();
 }
 
 static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
@@ -1849,7 +1846,6 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
             __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, PENDING_DEBUG_EXC_BS);
 
             domain_pause_for_debugger();
-            do_sched_op(SCHEDOP_yield, 0);
 
             break;
         }
index db428d617ff15454097271f205c728d1bad158d4..577e9660775c3b1b04cc1e008e134e5d7560bff3 100644 (file)
@@ -148,6 +148,7 @@ static inline int irq_masked(unsigned long eflags)
 
 extern void handle_mmio(unsigned long, unsigned long);
 extern void hvm_wait_io(void);
+extern void hvm_safe_block(void);
 extern void hvm_io_assist(struct vcpu *v);
 extern void pic_irq_request(int *interrupt_request, int level);
 extern void hvm_pic_assist(struct vcpu *v);